package com.guomei.service.exam.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.guomei.bean.curse.*;
import com.guomei.bean.exam.domain.Exam;
import com.guomei.bean.exam.domain.ExamAnswer;
import com.guomei.bean.exam.domain.ExamAnswerDetail;
import com.guomei.bean.exam.domain.ExamEnroll;
import com.guomei.bean.exam.domain.ExamEnrollDTO;
import com.guomei.bean.exam.vo.ExamOrder;
import com.guomei.bean.User;
import com.guomei.constans.ExamEnrollCode;
import com.guomei.mapper.curse.*;
import com.guomei.mapper.UserMapper;
import com.guomei.service.curse.ChannelService;
import com.guomei.service.exam.ExamEnrollService;
import com.guomei.utils.PageData;
import com.guomei.utils.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 考试报名服务实现类
 */
@Service
@Slf4j
@Transactional
public class ExamEnrollServiceImpl implements ExamEnrollService {
    
    @Resource
    private ExamEnrollMapper examEnrollMapper;
    
    @Resource
    private UserMapper userMapper;
    
    @Resource
    private ChannelMapper channelMapper;
    
    @Resource
    private ChannelService channelService;
    @Resource
    private CourseMapper courseMapper;
    @Resource
    private CourseChapterMapper courseChapterMapper;
    @Resource
    private CourseOrderMapper courseOrderMapper;
    @Resource
    private CourseClassAssociationMapper courseClassAssociationMapper;
    @Resource
    private ExamMapper examMapper;
    @Resource
    private ExamAnswerDetailMapper examAnswerDetailMapper;
    @Resource
    private ExamAnswerMapper examAnswerMapper;
    @Resource
    private UserCourseLearnMapper userCourseLearnMapper;

    @Override
    public ExamEnroll getById(Long id) {
        if (id == null) {
            return null;
        }
        return examEnrollMapper.selectById(id);
    }

    @Override
    public List<ExamEnroll> getAll() {
        return examEnrollMapper.selectAll();
    }

    @Override
    public Result<?> getByCondition(ExamEnroll examEnroll) {
        PageHelper.startPage(examEnroll.getPageNum(), examEnroll.getPageSize());
        List<ExamEnroll> examEnrolls = examEnrollMapper.selectByCondition(examEnroll);
        if (examEnrolls == null || examEnrolls.isEmpty()){
            return Result.fail("没有查询到数据");
        }else {
            for (ExamEnroll enroll : examEnrolls) {
                Exam exam = new Exam();
                exam.setId(enroll.getExamId());
                List<Exam> exams = examMapper.selectByCondition(exam);
                
                // 修复空列表访问问题
                List<ExamAnswer> examAnswers = examAnswerMapper.selectByEnrollId(enroll.getId());
                if (examAnswers != null && !examAnswers.isEmpty()) {
                    ExamAnswer examAnswer = examAnswers.get(0);
                    List<ExamAnswerDetail> examAnswerDetails = examAnswerDetailMapper.selectByAnswerId(examAnswer.getId());
                    enroll.setExamAnswerDetails(examAnswerDetails);
                } else {
                    log.info("报名ID {} 没有对应的答卷", enroll.getId());
                }
                
                if (exams == null || exams.isEmpty()){
                    log.info("考试不存在");
                }else {
                    Exam exam1 = exams.get(0);
                    enroll.setExam(exam1);
                }
            }
        }
        // 封装分页结果到PageData
        PageData<ExamEnroll> pageData = new PageData<>();
        PageInfo<ExamEnroll> pageInfo = new PageInfo<>(examEnrolls);
        pageData.setTotal(pageInfo.getTotal());
        pageData.setData(pageInfo.getList());
        pageData.setPageNum(examEnroll.getPageNum());
        pageData.setPageSize(examEnroll.getPageSize());
        return Result.success(pageData);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean save(ExamEnroll examEnroll) {
        if (examEnroll == null) {
            return false;
        }

        // 设置创建和更新时间
        LocalDateTime now = LocalDateTime.now();
        examEnroll.setEnrollTime(now);
        
        // 设置默认值
        if (examEnroll.getPayStatus() == null) {
            examEnroll.setPayStatus((short) ExamEnrollCode.PAY_STATUS_UNPAID.getCode());
        }
        if (examEnroll.getStatus() == null) {
            examEnroll.setStatus((short) ExamEnrollCode.STATUS_NORMAL.getCode());
        }
        if (examEnroll.getOrderNo() == null) {
            examEnroll.setOrderNo(generateOrderNo());
        }

        return examEnrollMapper.insert(examEnroll) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchSave(List<ExamEnroll> examEnrolls) {
        if (examEnrolls == null || examEnrolls.isEmpty()) {
            return false;
        }

        LocalDateTime now = LocalDateTime.now();
        for (ExamEnroll examEnroll : examEnrolls) {
            // 设置创建和更新时间
            examEnroll.setEnrollTime(now);
            
            // 设置默认值
            if (examEnroll.getPayStatus() == null) {
                examEnroll.setPayStatus((short) ExamEnrollCode.PAY_STATUS_UNPAID.getCode());
            }
            if (examEnroll.getStatus() == null) {
                examEnroll.setStatus((short) ExamEnrollCode.STATUS_NORMAL.getCode());
            }
            if (examEnroll.getOrderNo() == null) {
                examEnroll.setOrderNo(generateOrderNo());
            }
        }

        return examEnrollMapper.batchInsert(examEnrolls) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean update(ExamEnroll examEnroll) {
        if (examEnroll == null || examEnroll.getId() == null) {
            return false;
        }
        return examEnrollMapper.updateById(examEnroll) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeById(Long id) {
        if (id == null) {
            return false;
        }
        return examEnrollMapper.deleteById(id) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchRemove(List<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            return false;
        }
        return examEnrollMapper.batchDelete(ids) > 0;
    }

    @Override
    public List<ExamEnroll> getByExamId(Long examId) {
        if (examId == null) {
            return null;
        }
        return examEnrollMapper.selectByExamId(examId);
    }

    @Override
    public List<ExamEnroll> getByUserId(Long userId) {
        if (userId == null) {
            return null;
        }
        return examEnrollMapper.selectByUserId(userId);
    }

    @Override
    public ExamEnroll getByExamIdAndUserId(Long examId, Long userId) {
        if (examId == null || userId == null) {
            return null;
        }
        return examEnrollMapper.selectByExamIdAndUserId(examId, userId);
    }

    @Override
    public ExamEnroll getByExamIdAndIdCard(Long examId, String idCard) {
        if (examId == null || idCard == null) {
            return null;
        }
        return examEnrollMapper.selectByExamIdAndIdCard(examId, idCard);
    }

    @Override
    public ExamEnroll getByExamIdAndPhone(Long examId, String phone) {
        if (examId == null || phone == null) {
            return null;
        }
        return examEnrollMapper.selectByExamIdAndPhone(examId, phone);
    }

    @Override
    public ExamEnroll getByOrderNo(String orderNo) {
        if (orderNo == null) {
            return null;
        }
        return examEnrollMapper.selectByOrderNo(orderNo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeByExamId(Long examId) {
        if (examId == null) {
            return false;
        }
        return examEnrollMapper.deleteByExamId(examId) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeByUserId(Long userId) {
        if (userId == null) {
            return false;
        }
        return examEnrollMapper.deleteByUserId(userId) > 0;
    }

    @Override
    public int countByUserIdAndExamId(Long userId, Long examId) {
        if (userId == null || examId == null) {
            return 0;
        }
        return examEnrollMapper.countByUserIdAndExamId(userId, examId);
    }

    @Override
    public int countByExamId(Long examId) {
        if (examId == null) {
            return 0;
        }
        return examEnrollMapper.countByExamId(examId);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updatePaymentStatus(String orderNo, Short payStatus, Short payType, String tradeNo, String wxNo) {
        if (orderNo == null) {
            log.error("订单号不能为空");
            return false;
        }
        
        try {
            ExamEnroll examEnroll = examEnrollMapper.selectByOrderNo(orderNo);
            if (examEnroll == null) {
                log.error("找不到订单号为 {} 的考试报名记录", orderNo);
                return false;
            }
            
            // 更新支付状态
            examEnroll.setPayStatus(payStatus);
            examEnroll.setPayType(payType);
            examEnroll.setPayTime(LocalDateTime.now());
            
            // 根据支付类型设置对应的交易号
            if (payType != null) {
                if (payType == 1) { // 支付宝
                    examEnroll.setTradeNo(tradeNo);
                } else if (payType == 2) { // 微信支付
                    examEnroll.setWxNo(wxNo);
                }
            }
            
            int result = examEnrollMapper.updateById(examEnroll);
            log.info("更新考试报名支付状态成功，订单号：{}，支付状态：{}，支付类型：{}", orderNo, payStatus, payType);
            return result > 0;
            
        } catch (Exception e) {
            log.error("更新考试报名支付状态失败，订单号：{}", orderNo, e);
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> enrollExam(ExamEnrollDTO examEnrollDTO) {
        try {
            // 1. 验证报名资格
            Result<?> validateResult = validateEnrollQualification(examEnrollDTO.getExamId(), examEnrollDTO.getUserId());
            if (validateResult.getCode() != 200) {
                return validateResult;
            }

            // // 2. 检查是否已报名
            // ExamEnroll existingEnroll = getByExamIdAndUserId(examEnrollDTO.getExamId(), examEnrollDTO.getUserId());
            // if (existingEnroll != null) {
            //     return Result.fail("您已经报名过该考试");
            // }

            // // 3. 检查身份证号是否已被使用 （不需要啊！！，你多次考试，身份证号可以重复的）
            // ExamEnroll existingIdCard = getByExamIdAndIdCard(examEnrollDTO.getExamId(), examEnrollDTO.getIdCard());
            // if (existingIdCard != null) {
            //     return Result.fail("该身份证号已被使用");
            // }

            // // 4. 检查手机号是否已被使用（不需要啊！！，你多次考试，手机号可以重复的）
            // ExamEnroll existingPhone = getByExamIdAndPhone(examEnrollDTO.getExamId(), examEnrollDTO.getPhone());
            // if (existingPhone != null) {
            //     return Result.fail("该手机号已被使用");
            // }

            // 5. 创建报名记录
            ExamEnroll examEnroll = new ExamEnroll();
            examEnroll.setExamId(examEnrollDTO.getExamId());
            examEnroll.setUserId(examEnrollDTO.getUserId());
            examEnroll.setIdCard(examEnrollDTO.getIdCard());
            examEnroll.setPhone(examEnrollDTO.getPhone());
            examEnroll.setAddress(examEnrollDTO.getAddress());
            examEnroll.setAmount(examEnrollDTO.getAmount());
            examEnroll.setOrderNo(generateOrderNo());

            boolean success = save(examEnroll);
            if (success) {
                return Result.success("报名成功，请及时支付", examEnroll);
            } else {
                return Result.fail("报名失败");
            }

        } catch (Exception e) {
            log.error("考试报名失败", e);
            return Result.fail("报名失败：" + e.getMessage());
        }
    }

    @Override
    public Result<?> validateEnrollQualification(Long examId, Long userId) {
        try {
            // 1. 检查用户是否存在
            User user = userMapper.selectById(userId);
            if (user == null) {
                return Result.fail("用户不存在");
            }

            // 2. 检查用户状态
            if (user.getStatus() == 0) {
                return Result.fail("用户已被禁用");
            }

            // 3. 检查是否为渠道用户
            boolean isChannelUser = false;
            if (user.getChannelCode() != null && !user.getChannelCode().trim().isEmpty()) {
                Channel channel = channelMapper.selectByChannelCode(user.getChannelCode());
                if (channel != null && channel.getStatus() != null && channel.getStatus() == 1) {
                    isChannelUser = true;
                }
            }

            // 4. 如果是渠道用户，直接允许报名
            if (isChannelUser) {
                return Result.success("渠道用户，可以报名");
            }

            // 5. 检查用户报名次数
            int enrollCount = countByUserIdAndExamId(userId,examId);
            
            // 6. 如果报名次数超过3次，需要缴纳考试费
            if (enrollCount >= 3) {
                return Result.success("报名次数超过3次，需要缴纳考试费");
            }

            // TODO: 7. 检查是否报名了课程（这里需要根据实际的课程报名表来实现）
            // boolean hasEnrolledCourse = checkUserCourseEnrollment(userId,examId);
            // if (!hasEnrolledCourse) {
            //     return Result.fail("您还没有报名相关课程，无法参加考试");
            // }

            // 8. 检查课程完成度（这里需要根据实际的课程学习记录来实现）
            boolean courseCompleted = checkUserCourseCompletion(userId,examId);
            if (!courseCompleted) {
                return Result.fail("您还没有完成课程内容，无法参加考试");
            }

            return Result.success("验证通过，可以报名");

        } catch (Exception e) {
            log.error("验证报名资格失败", e);
            return Result.fail("验证失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> paySuccess(String orderNo) {
        try {
            if (orderNo == null) {
                return Result.fail("订单编号不能为空");
            }

            ExamEnroll examEnroll = getByOrderNo(orderNo);
            if (examEnroll == null) {
                return Result.fail("订单不存在");
            }

            if (examEnroll.getPayStatus() != null && examEnroll.getPayStatus() == ExamEnrollCode.PAY_STATUS_PAID.getCode()) {
                return Result.fail("订单已支付");
            }

            // 更新支付状态
            examEnroll.setPayStatus((short) ExamEnrollCode.PAY_STATUS_PAID.getCode());
            examEnroll.setPayTime(LocalDateTime.now());

            boolean success = update(examEnroll);
            if (success) {
                return Result.success("支付成功");
            } else {
                return Result.fail("支付状态更新失败");
            }

        } catch (Exception e) {
            log.error("支付成功处理失败", e);
            return Result.fail("处理失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> cancelEnroll(Long examId, Long userId) {
        try {
            if (examId == null || userId == null) {
                return Result.fail("参数不能为空");
            }

            ExamEnroll examEnroll = getByExamIdAndUserId(examId, userId);
            if (examEnroll == null) {
                return Result.fail("报名记录不存在");
            }

            if (examEnroll.getPayStatus() != null && examEnroll.getPayStatus() == ExamEnrollCode.PAY_STATUS_PAID.getCode()) {
                return Result.fail("已支付的报名无法取消");
            }

            examEnroll.setStatus((short) ExamEnrollCode.STATUS_CANCELLED.getCode());

            boolean success = update(examEnroll);
            if (success) {
                return Result.success("取消报名成功");
            } else {
                return Result.fail("取消报名失败");
            }

        } catch (Exception e) {
            log.error("取消报名失败", e);
            return Result.fail("取消失败：" + e.getMessage());
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> cancelEnrollByOrderNo(String orderNo) {
        try {
            if (orderNo == null || orderNo.trim().isEmpty()) {
                return Result.fail("订单号不能为空");
            }
            
            if (!orderNo.startsWith("EXAM")) {
                return Result.fail("订单号格式错误，必须以EXAM开头");
            }

            ExamEnroll examEnroll = getByOrderNo(orderNo);
            if (examEnroll == null) {
                return Result.fail("报名记录不存在");
            }

            // 检查支付状态，只有未支付的报名才能取消
            if (examEnroll.getPayStatus() != null && examEnroll.getPayStatus() == ExamEnrollCode.PAY_STATUS_PAID.getCode()) {
                return Result.fail("已支付的报名无法取消");
            }
            
            // 检查是否已经取消
            if (examEnroll.getStatus() != null && examEnroll.getStatus() == ExamEnrollCode.STATUS_CANCELLED.getCode()) {
                return Result.fail("报名已取消");
            }

            // 更新状态为已取消
            examEnroll.setStatus((short) ExamEnrollCode.STATUS_CANCELLED.getCode());

            boolean success = update(examEnroll);
            if (success) {
                log.info("根据订单号取消报名成功，订单号：{}", orderNo);
                return Result.success("取消报名成功");
            } else {
                log.error("根据订单号取消报名失败，订单号：{}", orderNo);
                return Result.fail("取消报名失败");
            }

        } catch (Exception e) {
            log.error("根据订单号取消报名异常，订单号：{}", orderNo, e);
            return Result.fail("取消失败：" + e.getMessage());
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean softDeleteEnroll(String orderNo) {
        if (orderNo == null || orderNo.trim().isEmpty()) {
            log.warn("订单号不能为空");
            return false;
        }
        
        if (!orderNo.startsWith("EXAM")) {
            log.warn("订单号格式错误，必须以EXAM开头: orderNo={}", orderNo);
            return false;
        }
        
        try {
            ExamEnroll examEnroll = getByOrderNo(orderNo);
            if (examEnroll == null) {
                log.warn("报名记录不存在: orderNo={}", orderNo);
                return false;
            }
            
            // 设置软删除标志
            examEnroll.setIsDeleted(true);
            
            boolean result = update(examEnroll);
            if (result) {
                log.info("软删除报名记录成功: orderNo={}", orderNo);
                return true;
            } else {
                log.warn("软删除报名记录失败: orderNo={}", orderNo);
                return false;
            }
            
        } catch (Exception e) {
            log.error("软删除报名记录异常: orderNo={}", orderNo, e);
            return false;
        }
    }

    /**
     * 生成订单编号
     */
    private String generateOrderNo() {
        return "EXAM" + System.currentTimeMillis() + UUID.randomUUID().toString().substring(0, 8).toUpperCase();
    }

    /**
     * 检查用户课程报名情况
     *
     */
    private boolean checkUserCourseEnrollment(Long userId,Long examId) {
        // 这里需要根据实际的课程报名表来实现
        ArrayList<Integer> buyed = new ArrayList<>();
        Exam exam = examMapper.selectById(examId);
        List<CourseOrder> courseOrders = courseOrderMapper.selectByUserId(userId, (short) 1);
        List<Course> courses = courseMapper.selectCourseTypeIsOne();
        if (courses != null && !courses.isEmpty()){
            log.info("查询公开课数量：{}", courses.size());
            for (Course cours : courses) {
                //添加公开课
                buyed.add(cours.getId().intValue());
            }
        }
        if (courseOrders != null && !courseOrders.isEmpty()){
            log.info("查询已购课程数量：{}", courseOrders.size());
            for (CourseOrder courseOrder : courseOrders) {
                Long courseId = courseOrder.getCourseId();
                Course courseCheck = courseMapper.selectById(courseOrder.getCourseId());
                if (courseCheck.getCourseType() != null && (courseCheck.getCourseType() == 3 || courseCheck.getCourseType() == 4)) {
                    //添加专研班和专修班下面的课程id
                    List<CourseClassAssociation> courseClassAssociations = courseClassAssociationMapper.selectByMainCourseId(courseCheck.getId());
                    log.info("查询专研班和专修班下面课程数量：{}", courseClassAssociations.size());
                    for (CourseClassAssociation courseClassAssociation : courseClassAssociations) {
                        buyed.add(courseClassAssociation.getDeputyCourseId().intValue());
                    }
                } else {
                    //添加收费课的课程id
                    log.info("查询收费课程数量：{}", courseId);
                    buyed.add(courseId.intValue());
                }
            }
        }
        if (exam.getCourseId() != null){
            if(buyed.contains(exam.getCourseId().intValue())){
                return true;
            }else {
                return false;
            }
        } else {
            return true;
        }
    }

    /**
     * 检查用户课程完成情况
     *
     */
    private boolean checkUserCourseCompletion(Long userId, Long examId) {
        // 这里需要根据实际的课程学习记录来实现
        // 暂时返回true，表示已完成课程
        Exam exam = examMapper.selectById(examId);
        if (exam.getCourseId() == null){
            return false;
        }
        UserCourseLearn userCourseLearn = new UserCourseLearn();
        userCourseLearn.setUserId(userId);
        userCourseLearn.setCourseId(exam.getCourseId());
        List<UserCourseLearn> userCourseLearns = userCourseLearnMapper.selectByCondition(userCourseLearn);
        for (UserCourseLearn courseLearn : userCourseLearns) {
            if (courseLearn.getStatus() != 1){
                return false;
            }
        }
        return true;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateWxNoByOrderNo(String orderNo, String wxNo) {
        try {
            if (orderNo == null || orderNo.trim().isEmpty()) {
                log.error("订单号不能为空");
                return false;
            }
            
            if (wxNo == null || wxNo.trim().isEmpty()) {
                log.error("微信交易号不能为空");
                return false;
            }
            
            ExamEnroll examEnroll = getByOrderNo(orderNo);
            if (examEnroll == null) {
                log.error("报名记录不存在: orderNo={}", orderNo);
                return false;
            }
            
            examEnroll.setWxNo(wxNo);
            boolean success = update(examEnroll);
            
            if (success) {
                log.info("成功更新考试报名微信交易号: orderNo={}, wxNo={}", orderNo, wxNo);
            } else {
                log.error("更新考试报名微信交易号失败: orderNo={}, wxNo={}", orderNo, wxNo);
            }
            
            return success;
            
        } catch (Exception e) {
            log.error("更新考试报名微信交易号异常: orderNo={}, wxNo={}", orderNo, wxNo, e);
            return false;
        }
    }

    @Override
    public Result<?> getOrderDetail(String orderNo) {
        if (orderNo == null || orderNo.trim().isEmpty()) {
            return Result.fail("订单号不能为空");
        }

        ExamOrder examOrder = new ExamOrder();
        ExamEnroll examEnroll = getByOrderNo(orderNo);
        if (examEnroll == null) {
            return Result.fail("报名记录不存在");
        }
        Exam exam = examMapper.selectById(examEnroll.getExamId());
        User buyUser = userMapper.selectById(examEnroll.getUserId());
        Course course = courseMapper.selectById(exam.getCourseId());
        if (course != null) {
            User teacher = userMapper.selectById(course.getTeacherId());
            examOrder.setTeacher(teacher);
        }
        examOrder.setExamEnroll(examEnroll);
        examOrder.setExam(exam);
        examOrder.setBuyUser(buyUser);
        return Result.success(examOrder);
    }
}
